package com.jprocms.module.cms.permission;

import cn.hutool.core.util.ObjectUtil;
import com.jpro.framework.common.enums.UserTypeEnum;
import com.jpro.framework.common.util.json.JsonUtils;
import com.jpro.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
import com.jpro.framework.security.core.LoginUser;
import com.jpro.framework.security.core.util.SecurityFrameworkUtils;
import com.jpro.module.system.api.permission.PermissionApi;
import com.jpro.module.system.api.permission.dto.ChannelPermissionRespDTO;
import com.jpro.module.system.api.permission.dto.ContentPermissionRespDTO;
import com.jpro.module.system.api.permission.dto.DeptDataPermissionRespDTO;
import com.jpro.module.system.api.permission.dto.SitePermissionRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * Content PermissionRule 是mybatisplus增加机制实现，这里还需要mybatis查询栏目数据，后面主查询使用的是mybatis  xml 实现
 */
@Slf4j
@Service
public class PermissionServiceImpl implements PermissionService {
    private PermissionApi permissionApi;

    public PermissionServiceImpl(PermissionApi permissionApi) {
        this.permissionApi = permissionApi;
    }

    /**
     * LoginUser 的 Context 缓存 Key  栏目类
     */
    protected static final String CONTEXT_KEY_CONTENT = ContentPermissionRule.class.getSimpleName();

    /**
     * LoginUser 的 Context 缓存 Key 内容类
     */
    protected static final String CONTEXT_KEY_CHANNEL = ChannelPermissionRule.class.getSimpleName();

    /**
     * LoginUser 的 Context 缓存 Key  站群
     */
    protected static final String CONTEXT_KEY_SITE = SitePermissionRule.class.getSimpleName();
    /**
     * LoginUser 的 Context 缓存 Key 数据范围权限
     */
    protected static final String CONTEXT_KEY_SCOPE = DeptDataPermissionRule.class.getSimpleName();

    public ContentPermissionRespDTO getContentPermission() {
        // 只有有登陆用户的情况下，才进行数据权限的处理
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        // 只有管理员类型的用户，才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }

        // 获得数据权限
        ContentPermissionRespDTO contentPermission = loginUser.getContext(CONTEXT_KEY_CONTENT, ContentPermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (contentPermission == null) {
            contentPermission = permissionApi.getContentPermission(loginUser.getId()).getCheckedData();
            if (contentPermission == null) {
                log.debug("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d)  未返回数据权限", loginUser.getId()));
            }
            // 添加到上下文中，避免重复计算
            loginUser.setContext(CONTEXT_KEY_CONTENT, contentPermission);
        }
        return contentPermission;
    }

    public ChannelPermissionRespDTO getChannelPermission() {
        // 只有有登陆用户的情况下，才进行数据权限的处理
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        // 只有管理员类型的用户，才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }

        // 获得数据权限
        ChannelPermissionRespDTO channelPermission = loginUser.getContext(CONTEXT_KEY_CHANNEL, ChannelPermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (channelPermission == null) {
            channelPermission = permissionApi.getChannelPermission(loginUser.getId()).getCheckedData();
            if (channelPermission == null) {
                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d) 未返回数据权限", loginUser.getId()));
            }
            // 添加到上下文中，避免重复计算
            loginUser.setContext(CONTEXT_KEY_CHANNEL, channelPermission);
        }
        return channelPermission;
    }


    public SitePermissionRespDTO getSitePermission() {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        // 只有管理员类型的用户，才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }

        // 获得数据权限
        SitePermissionRespDTO sitePermission = loginUser.getContext(CONTEXT_KEY_SITE, SitePermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (sitePermission == null) {
            sitePermission = permissionApi.getSitePermission(loginUser.getId()).getCheckedData();
            if (sitePermission == null) {
                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d) 未返回数据权限", loginUser.getId()));
            }
            // 添加到上下文中，避免重复计算
            loginUser.setContext(CONTEXT_KEY_SITE, sitePermission);
        }
        return sitePermission;
    }

    @Override
    public DeptDataPermissionRespDTO getDeptPermission() {
        // 只有有登陆用户的情况下，才进行数据权限的处理
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null) {
            return null;
        }
        // 只有管理员类型的用户，才进行数据权限的处理
        if (ObjectUtil.notEqual(loginUser.getUserType(), UserTypeEnum.ADMIN.getValue())) {
            return null;
        }

        // 获得数据权限
        DeptDataPermissionRespDTO deptDataPermission = loginUser.getContext(CONTEXT_KEY_SCOPE, DeptDataPermissionRespDTO.class);
        // 从上下文中拿不到，则调用逻辑进行获取
        if (deptDataPermission == null) {
            deptDataPermission = permissionApi.getDeptDataPermission(loginUser.getId()).getCheckedData();
            if (deptDataPermission == null) {
                log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
                throw new NullPointerException(String.format("LoginUser(%d) 未返回数据权限", loginUser.getId()));
            }
            // 添加到上下文中，避免重复计算
            loginUser.setContext(CONTEXT_KEY_SCOPE, deptDataPermission);
        }

        return deptDataPermission;
    }
}
